package com.crowdfunding.backend.controller;

import com.crowdfunding.backend.dto.*;
import com.crowdfunding.backend.repo.UserRepository;
import com.crowdfunding.backend.security.JwtUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Optional;
import io.jsonwebtoken.Claims;
import java.time.Instant;

@RestController
@RequestMapping("/api")
@Validated
public class AuthController {

    private final UserRepository users;
    private final JwtUtil jwt;

    public AuthController(UserRepository users, JwtUtil jwt) {
        this.users = users;
        this.jwt = jwt;
    }

    @PostMapping("/register")
    public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest body) {
        if (users.findByEmail(body.email).isPresent()) {
            return ResponseEntity.status(409).body(new ErrorResponse("email already exists"));
        }
        String pwHash = BCrypt.hashpw(body.password, BCrypt.gensalt());
        long now = Instant.now().toEpochMilli();
        int id = users.create(body.username, body.email, pwHash, null, now);
        UserDto dto = users.findById(id).orElse(null);
        String token = jwt.generateToken(id, dto.username);
        return ResponseEntity.ok(new AuthResponse(token, dto));
    }

    @PostMapping("/login")
    public ResponseEntity<?> login(@Valid @RequestBody AuthRequest body) {
        Optional<com.crowdfunding.backend.dto.UserDto> opt = users.findByEmail(body.email);
        if (!opt.isPresent()) return ResponseEntity.status(401).body(new ErrorResponse("Invalid credentials"));
        com.crowdfunding.backend.dto.UserDto row = opt.get();
        Optional<String> phOpt = users.getPasswordHashByEmail(body.email);
        if (!phOpt.isPresent()) return ResponseEntity.status(401).body(new ErrorResponse("Invalid credentials"));
        String pwHash = phOpt.get();
        boolean ok = BCrypt.checkpw(body.password, pwHash);
        if (!ok) return ResponseEntity.status(401).body(new ErrorResponse("Invalid credentials"));
        String token = jwt.generateToken(row.id, row.username);
        return ResponseEntity.ok(new AuthResponse(token, row));
    }

    @GetMapping("/me")
    public ResponseEntity<?> me() {
        Object principal = org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication();
        if (principal == null || org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal() == null) {
            return ResponseEntity.status(401).body(new ErrorResponse("Missing token"));
        }
        try {
            String subj = (String) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            int id = Integer.parseInt(subj);
            Optional<com.crowdfunding.backend.dto.UserDto> opt = users.findById(id);
            if (!opt.isPresent()) return ResponseEntity.status(404).body(new ErrorResponse("User not found"));
            java.util.Map<String, Object> m = new java.util.HashMap<>();
            m.put("user", opt.get());
            return ResponseEntity.ok(m);
        } catch (Exception e) {
            return ResponseEntity.status(401).body(new ErrorResponse("Invalid token"));
        }
    }

    @PostMapping("/me/eoa")
    public ResponseEntity<?> updateEoa(@RequestBody java.util.Map<String,String> body) {
        if (org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication() == null) {
            return ResponseEntity.status(401).body(new ErrorResponse("Missing token"));
        }
        try {
            String subj = (String) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            int id = Integer.parseInt(subj);
            String eoa = body.get("eoaAddress");
            if (eoa == null) return ResponseEntity.status(400).body(new ErrorResponse("eoaAddress required"));
            users.updateEoaById(id, eoa);
            return ResponseEntity.ok(java.util.Collections.singletonMap("ok", true));
        } catch (Exception e) {
            return ResponseEntity.status(401).body(new ErrorResponse("Invalid token"));
        }
    }
}
